#include "c3_main.h"
#include "zhi_xing.h"
#include "gatts_table_creat_demo.h" //ble蓝牙

#include "socket.h"
#include "wifi.h" //WIFI
#include "esp_mac.h"
#include <sys/time.h>


#include <esp_ping.h>
#include "ping/ping_sock.h"

#define ROUTER_IP "192.168.1.12" // 路由器的IP地址
#define PING_TIMEOUT 5000        // ping超时时间（毫秒）

static char *sbm = SHE_BEI_MA;
// static QueueHandle_t ledPwmLD = NULL;  // PWM控制的 消息队列 QueueHandle_t
static QueueHandle_t kongZhiLD = NULL; // 系统设置的消息队列
static uint16_t kaiShiShi = 0;         // 中断启用开始时间(时)
static uint16_t jieShuShi = 23;        // 中断启用结束时间(时)
static uint16_t kaiShiFen = 0;         // 中断启用开始时间(分)
static uint16_t jieShuFen = 59;        // 中断启用结束时间(分)

static const char *TAG = "ZHI_XING: ";
static TaskHandle_t juBing;

static bool xhPanDuan = true; // sockets连接成功标志

void queue_init()
{
    // 创建一个队列
    kongZhiLD = xQueueCreate(4, sizeof(jsonJ));
    // ledPwmLD = xQueueCreate(10, sizeof(uint16_t)); //
    // if (kongZhiLD == NULL || NULL == ledPwmLD)
    if (kongZhiLD == NULL)
    {
        ESP_LOGW(TAG, "xiao xi 队列创建失败!\n");
    }
}
void fan_hui_sockets_xin_xi()
{
    if (xhPanDuan)
    {
        char fanhui[32] = {0};
        sprintf(fanhui, "{\"id\":\"%s\",\"fh\":99}", sbm);
        sockets_faSong(fanhui);
    }
}
void task_socket_1(void *pvParameter)
{
    /*
    uint8_t mac[6];
    esp_read_mac(mac, ESP_MAC_WIFI_STA); // 获取MAC地址
    // 将MAC地址转换为字符串格式

    char mac_str[18];
   snprintf(mac_str, sizeof(mac_str), "%02x:%02x:%02x:%02x:%02x:%02x",
             mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
*/
    uint16_t shijain = 0;
    char xiTiaoL[32] = {0};
    sprintf(xiTiaoL, "{\"id\":\"%s\",\"fh\":1}", sbm);
    char ip[16] = {0};
    if (ESP_OK != nvs_du_qu_str(MING_MING_KONG_JIA_1, "ip", ip))
    {
        ESP_LOGI(TAG, "socket 信息读取失败!\n");
    }
    while (1)
    {
#if TIAO_SHI == 0
        if (init_sockets(8080, ip)) // 连接sockets服务器
#elif TIAO_SHI == 1
        if (init_sockets(8080, "192.168.2.3")) // 连接sockets服务器
#elif TIAO_SHI == 2
        if (init_sockets(8080, "www.tianxialian.cn")) // 连接sockets服务器
#endif
        {
            // sockets_faSong("SBID\\c3001"); // 发送消息到sockets服务器
            if (sockets_faSong(xiTiaoL))
            {
                xhPanDuan = true;
            }
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            while (xhPanDuan)
            {
                if (2 == sockets_jieShou() || 4 == sockets_jieShou())
                {
                    close_sockets(); // 释放连接,从新连接
                    xhPanDuan = false;
                }
                // sockets_jieShou(); // 接收sockets服务器的消息
                vTaskDelay(200 / portTICK_PERIOD_MS);
                shijain++;
                if (shijain > 5 * 180) // 180秒
                {
                    shijain = 0;
                    sockets_faSong(xiTiaoL); // 发送心跳消息到sockets服务器
                }
            }
        }
        // ESP_LOGI(TAG, "远程 本地 socket 连接失败!\n");
        close_sockets();
        vTaskDelay(5000 / portTICK_PERIOD_MS);
    }
}

void xi_tong_kong_zhi(void *pvParameter)
{
    uint8_t ucRxData[KONGZHIP_XIAO_XI];
    size_t xReceivedBytes;
    const TickType_t xBlockTime = pdMS_TO_TICKS(20);
    float zkbGaiBian = 0;
    TickType_t yanShiJI = 0;
    bool wifiQiTing = false;
    jsonJ sjJP;
    bool zhongDuanKaiGuan = true;
    while (1)
    {
        // 从队列中接收数组地址
        if (xQueueReceive(kongZhiLD, &sjJP, portMAX_DELAY)) // 阻塞接收
        {

            uint16_t ss = sjJP.lx;
            // ESP_LOGI(TAG, "接收到队列消息: %d", ss);
            switch (sjJP.lx)
            {
            case 11: // WIFI连接
                ESP_LOGI(TAG, "*-OK----jian li task_socket_1 xian chen---------*\n");
                vTaskDelay(100 / portTICK_PERIOD_MS);
                xTaskCreate(task_socket_1, "task_socket_1", 1024 * 3, NULL, 11, &juBing);
                break;
            case 12: // WIFI断开
                ESP_LOGI(TAG, "*-NO----zhu xiao task_socket_1 xian chen---------*\n");
                close_sockets();
                vTaskDelete(juBing);
                break;
            case 13: // 关闭蓝牙
                if (ESP_OK == esp_bt_controller_disable())
                {
                    fan_hui_sockets_xin_xi();
                }
                break;
            case 14: // 设置WIFI连接信息wifi_set("wwcccxxx\\chenxin1234567890")
                if (wifi_set(&sjJP))
                {
                    fan_hui_sockets_xin_xi();
                    vTaskDelay(1000 / portTICK_PERIOD_MS);
                    esp_restart(); // 重启
                }
                break;
            case 15: // 保存socket连接信息
                if (ESP_OK == nvs_tian_jia_wangLuo(&sjJP))
                {
                    fan_hui_sockets_xin_xi();
                    vTaskDelay(2000 / portTICK_PERIOD_MS);
                    esp_restart(); // 重启
                }
                ESP_LOGI(TAG, "socket 信息写入失败!\n");
                break;
            case 16:
                esp_restart(); // 重启
                break;
            case 31: // 设置中断生效时
                if (nvs_bao_cun_shi_jian(&sjJP))
                {
                    fan_hui_sockets_xin_xi();
                }
                break; //{\"id\":\"c3001\",\"fh\":1}
            case 32:   // 设置中断生效分
                if (nvs_bao_cun_shi_jian(&sjJP))
                {
                    fan_hui_sockets_xin_xi();
                }
                break;
            case 33: // 设置LED亮度
                if (sjJP.kaiShi <= 0 && sjJP.kaiShi > 10)
                {
                    break;
                }
                if (ESP_OK == nvs_set_liang_du(sjJP.kaiShi))
                {
                    uint16_t llx = 4;
                    xQueueSend(ledPwmLD, &llx, pdMS_TO_TICKS(100));
                    fan_hui_sockets_xin_xi();
                    break;
                }
                ESP_LOGI(TAG, "liang_du 信息写入失败!\n");
                break;
            default:
                break;
            }
        }
        vTaskDelay(300 / portTICK_PERIOD_MS);
    }
}

// 多线程,从队列接收的任务。
void led_pwm(void *pvParameters)
{ // vTaskDelete(NULL)可以用于删除任务自身。
    uint8_t ucRxData[PWNP_XIAO_XI];
    size_t xReceivedBytes;
    // const TickType_t xBlockTime = pdMS_TO_TICKS(20);
    float zkbGaiBian = 0;
    uint16_t liangDuL = 0;
    // TickType_t yanShiJI = 0;//0-4294967295
    uint16_t yanShiJI = 0; // 0-65535
    bool qiTingJB = false;
    bool yuanChenQiTingJB = false;
    uint16_t lx = 0;
    if (ESP_OK == nvs_get_liang_du(&liangDuL))
    {
        ESP_LOGI(TAG, "读取的的亮度为: %d\n", liangDuL);
        zkbGaiBian = (float)liangDuL / 10.0;
    }
    else
    {
        zkbGaiBian = 0.5;
    }
    while (1)
    { /*
         // 接收消息
         // 从消息缓冲区接收下一条消息。在阻塞状态下等待（因此不使用任何 CPU 处理时间）最多 100 毫秒，消息才可用。
         xReceivedBytes = xMessageBufferReceive(pwmP,
                                                (void *)ucRxData,
                                                sizeof(ucRxData),
                                                xBlockTime);

         if (xReceivedBytes > 0)
         */

        // 从队列中接收数组地址
        // if(lx)
        if (xQueueReceive(ledPwmLD, &lx, pdMS_TO_TICKS(50))) // 阻塞50毫秒
        {
            switch (lx)
            {
            case 1:
                // ESP_LOGI(TAG, "现在的占空比为: %f", zkbGaiBian);
                if (!yuanChenQiTingJB)
                {
                    qiTingJB = true;
                    ledPwmTianYao(zkbGaiBian);
                    yanShiJI = 0;
                    lx = 0;
                }
                break;
            case 2:
                lx = 0;
                qiTingJB = false;
                yuanChenQiTingJB = false;
                ledPwmTianYao(0);
                ESP_LOGI(TAG, "停止  现在的占空比为: 0\n");
                break;
            case 3:
                lx = 0;
                qiTingJB = false;
                yuanChenQiTingJB = true;
                ledPwmTianYao(zkbGaiBian);
                ESP_LOGI(TAG, "现在的占空比为: %f\n", zkbGaiBian);
                break;
            case 4:
                if (ESP_OK == nvs_get_liang_du(&liangDuL))
                {
                    ESP_LOGI(TAG, "现在的亮度为: %d\n", liangDuL);
                    zkbGaiBian = (float)liangDuL / 10.0;
                }
                break;
            case 5:
                lx = 0;
                qiTingJB = false;
                yuanChenQiTingJB = true;
                ledPwmTianYao(0);
                break;
            default:
                break;
            }
        }
        if (qiTingJB)
        {
            yanShiJI++;
            if (yanShiJI > 10 * 50)
            {
                qiTingJB = false;
                ledPwmTianYao(0);
                //ESP_LOGI(TAG, "现在的占空比为: 0");
            }
        }
        vTaskDelay(100 / portTICK_PERIOD_MS);
    }
}

void xiao_xi_fen_fa(void *arg)
{
    uint8_t ucRxData[KONGZHIP_XIAO_XI];
    size_t xReceivedBytes = 0;
    //{\"id\":\"c3001\",\"lx\":2,}
    while (true)
    {
        xReceivedBytes = xMessageBufferReceive(zhuanFanP, (void *)ucRxData, sizeof(ucRxData), pdMS_TO_TICKS(20));
        if (xReceivedBytes > 0)
        {
            json_chu_li((char *)ucRxData);
            memset(ucRxData,0,KONGZHIP_XIAO_XI);
        }
        vTaskDelay(300 / portTICK_PERIOD_MS);
    }
}

/******************掉电保存**********************/
bool wifi_set(jsonJP jsonP)
{
    esp_err_t err;
    err = nvs_tian_jia_str(MING_MING_KONG_JIA_1, "wi_fi", jsonP->ips);
    if (err != ESP_OK)
    {
        printf("Error (%s) saving restart counter to NVS!\n", esp_err_to_name(err));
        return false;
    }
    err = nvs_tian_jia_str(MING_MING_KONG_JIA_1, "pass", jsonP->vvs);
    if (err != ESP_OK)
    {
        printf("Error (%s) saving restart counter to NVS!\n", esp_err_to_name(err));
        return false;
    }
    return true;
}

bool wifi_Start()
{
    #if TIAO_SHI == 2
    wifi_init("cccxxx", "chenxin1234567890");
#endif
    char ssid[WIFI_SSID_LEN] = {0};
    char pass[WIFI_PASS_LEN] = {0};
    esp_err_t err;
    err = nvs_du_qu_str(MING_MING_KONG_JIA_1, "wi_fi", ssid);
    if (err != ESP_OK)
    {
        printf("Error (%s) du qu WIFI SSID!\n", esp_err_to_name(err));
        return false;
    }
    err = nvs_du_qu_str(MING_MING_KONG_JIA_1, "pass", pass);
    if (err != ESP_OK)
    {
        printf("Error (%s) du qu WIFI PASS!\n", esp_err_to_name(err));
        return false;
    }
#if TIAO_SHI == 0
    wifi_init(ssid, pass);
#elif TIAO_SHI == 1
    wifi_init("cccxxx", "chenxin1234567890");
#endif
    return true;
}

esp_err_t nvs_du_qu_str(const char *mingMingKongJIanI8P, const char *key, char *strSZP)
{
    nvs_handle_t my_handle;
    esp_err_t err;
    size_t len = 0;
    // Open
    err = nvs_open(mingMingKongJIanI8P, // 命名空间名称
                   NVS_READWRITE,       // NVS_READWRITE 或 NVS_READONLY。如果 NVS_READONLY，将打开一个只读句柄。
                   &my_handle);         // 如果成功（返回代码为零），句柄将在此参数中返回。
    if (err != ESP_OK)
    {
        ESP_LOGI(TAG, "err ==  1\n");
        nvs_close(my_handle);
        return err;
    }
    /*这个是获取要获取的字符串长度,包含终止符'\0'*/
    err = nvs_get_str(my_handle, key, NULL, &len); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回,包含'\0'。
    if (err != ESP_OK)
    {
        ESP_LOGI(TAG, "err ==  2\n");
        nvs_close(my_handle);
        return err;
    }
    char *run_time = malloc(len); // malloc 动态分配内存
    /*这个是获取指定长度的字符串*/
    err = nvs_get_str(my_handle, key, run_time, &len); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回。
    if (err != ESP_OK)
    {
        ESP_LOGI(TAG, "err ==  3\n");
        free(run_time);
        nvs_close(my_handle);
        return err;
    }
    // ESP_LOGI(TAG, "run_time ==  %s\n", run_time);
    for (size_t i = 0; i < len; i++)
    {
        strSZP[i] = run_time[i];
    }
    // ESP_LOGI(TAG, "strSZP ==  %s\n", strSZP);

    free(run_time); // 释放分配的动态内存

    // 关闭存储句柄并释放所有分配的资源
    nvs_close(my_handle);
    return ESP_OK;
}

esp_err_t nvs_du_qu_value(const char *mingMingKongJIanI8P, const char *key, void *value, uint8_t lx)
{
    nvs_handle_t my_handle;
    esp_err_t err;
    // Open
    err = nvs_open(mingMingKongJIanI8P, // 命名空间名称
                   NVS_READWRITE,       // NVS_READWRITE 或 NVS_READONLY。如果 NVS_READONLY，将打开一个只读句柄。
                   &my_handle);         // 如果成功（返回代码为零），句柄将在此参数中返回。
    if (err != ESP_OK)
    {
        ESP_LOGI(TAG, "Error (%s) saving restart counter to NVS!\n", esp_err_to_name(err));
        return err;
    }

    if (lx == 1)
    {
        uint16_t valuels = 0;
        /*这些函数根据键的名称检索键的值*/
        err = nvs_get_u16(my_handle, key, &valuels); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回,包含'\0'。
        if (err != ESP_OK)
        {
            return err;
        }
        *(u_int16_t *)value = valuels;
    }
    else if (lx == 2)
    {
        uint32_t valuels = 0;
        /*这些函数根据键的名称检索键的值*/
        err = nvs_get_u32(my_handle, key, &valuels); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回,包含'\0'。
        if (err != ESP_OK)
        {
            return err;
        }
        *(u_int32_t *)value = valuels;
    }

    // 关闭存储句柄并释放所有分配的资源
    nvs_close(my_handle);
    return ESP_OK;
}

esp_err_t nvs_tian_jia_str(const char *mingMingKongJIanI8P, const char *key, const char *str)
{
    nvs_handle_t my_handle;
    esp_err_t err;

    // Open
    err = nvs_open(mingMingKongJIanI8P, // 命名空间名称
                   NVS_READWRITE,       // NVS_READWRITE 或 NVS_READONLY。如果 NVS_READONLY，将打开一个只读句柄。
                   &my_handle);         // 如果成功（返回代码为零），句柄将在此参数中返回。
    if (err != ESP_OK)
    {
        nvs_close(my_handle);
        return err;
    }
    err = nvs_set_str(my_handle, key, str); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回。
    if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND)
    {
        nvs_close(my_handle);
        return err;
    }
    //  承诺书面价值。设置任何值后，必须调用 nvs_commit() 以确保更改写入闪存。
    //  实现可能会在其他时间写入存储，但这不能保证。
    err = nvs_commit(my_handle);
    if (err != ESP_OK)
    {
        nvs_close(my_handle);
        return err;
    }

    // 关闭存储句柄并释放所有分配的资源
    nvs_close(my_handle);
    return ESP_OK;
}

esp_err_t nvs_tian_jia_wangLuo(jsonJP jsonP)
{
    nvs_handle_t my_handle;
    esp_err_t err;
    // Open
    err = nvs_open(MING_MING_KONG_JIA_1, // 命名空间名称
                   NVS_READWRITE,        // NVS_READWRITE 或 NVS_READONLY。如果 NVS_READONLY，将打开一个只读句柄。
                   &my_handle);          // 如果成功（返回代码为零），句柄将在此参数中返回。
    if (err != ESP_OK)
    {
        nvs_close(my_handle);
        return err;
    }
    err = nvs_set_str(my_handle, jsonP->ips, jsonP->vvs); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回。
    if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND)
    {
        nvs_close(my_handle);
        return err;
    }
    // 设置任何值后，必须调用 nvs_commit() 以确保更改写入闪存。
    //  实现可能会在其他时间写入存储，但这不能保证
    err = nvs_commit(my_handle);
    if (err != ESP_OK)
    {
        nvs_close(my_handle);
        return err;
    }
    // 关闭存储句柄并释放所有分配的资源
    nvs_close(my_handle);
    return ESP_OK;
}

esp_err_t nvs_set_liang_du(uint16_t ld)
{
    nvs_handle_t my_handle;
    esp_err_t err;
    // Open
    err = nvs_open(ZIDINGYI_NVS_KONG_JIAN, // 命名空间名称
                   NVS_READWRITE,          // NVS_READWRITE 或 NVS_READONLY。如果 NVS_READONLY，将打开一个只读句柄。
                   &my_handle);            // 如果成功（返回代码为零），句柄将在此参数中返回。
    if (err != ESP_OK)
    {
        nvs_close(my_handle);
        return err;
    }
    err = nvs_set_u16(my_handle, "liangDu", ld);
    if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND)
    {
        nvs_close(my_handle);
        return err;
    }
    // 设置任何值后，必须调用 nvs_commit() 以确保更改写入闪存。
    //  实现可能会在其他时间写入存储，但这不能保证
    err = nvs_commit(my_handle);
    if (err != ESP_OK)
    {
        nvs_close(my_handle);
        return err;
    }
    // 关闭存储句柄并释放所有分配的资源
    nvs_close(my_handle);
    return ESP_OK;
}

esp_err_t nvs_get_liang_du(uint16_t *ld)
{
    nvs_handle_t my_handle;
    esp_err_t err;
    // Open
    err = nvs_open(ZIDINGYI_NVS_KONG_JIAN, // 命名空间名称
                   NVS_READWRITE,          // NVS_READWRITE 或 NVS_READONLY。如果 NVS_READONLY，将打开一个只读句柄。
                   &my_handle);            // 如果成功（返回代码为零），句柄将在此参数中返回。
    if (err != ESP_OK)
    {
        nvs_close(my_handle);
        return err;
    }
    err = nvs_get_u16(my_handle, "liangDu", ld);
    if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND)
    {
        nvs_close(my_handle);
        return err;
    }
    // 关闭存储句柄并释放所有分配的资源
    nvs_close(my_handle);
    return ESP_OK;
}

void nvs_init()
{
    esp_err_t err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        // NVS分区被截断，需要擦除重试nvs_flash_init
        ESP_ERROR_CHECK(nvs_flash_erase());
        err = nvs_flash_init();
    }
    ESP_ERROR_CHECK(err);
}

void nvs_erase()
{
    esp_err_t err;
    // NVS分区被截断，需要擦除重试nvs_flash_init
    err = nvs_flash_erase();
    if (err != ESP_OK)
    {
        printf("Error (%s) saving restart counter to NVS!\n", esp_err_to_name(err));
    }
    err = nvs_flash_init();
    ESP_ERROR_CHECK(err);
}

bool delete_wifi_credentials()
{
    nvs_handle my_handle;
    esp_err_t err;
    // 打开NVS分区
    err = nvs_open("storage", NVS_READWRITE, &my_handle);
    if (err != ESP_OK)
    {
        nvs_close(my_handle);
        return false;
    }
    // 删除Wi-Fi SSID和密码的键值对
    err = nvs_erase_key(my_handle, "wifi_ssid");
    if (err != ESP_OK)
    {
        nvs_close(my_handle);
        return false;
    }
    err = nvs_erase_key(my_handle, "wifi_password");
    if (err != ESP_OK)
    {
        nvs_close(my_handle);
        return false;
    }
    err = nvs_commit(my_handle);
    // 关闭NVS分区
    nvs_close(my_handle);
    return true;
}

bool nvs_shan_chu_all(jsonJP jsonP)
{
    nvs_handle my_handle;
    esp_err_t err;
    // 打开NVS分区
    err = nvs_open(jsonP->ips, NVS_READWRITE, &my_handle);
    if (err != ESP_OK)
    {
        nvs_close(my_handle);
        return false;
    }
    err = nvs_erase_all((char *)(jsonP->ips));
    if (ESP_OK != err)
    {
        nvs_close(my_handle);
        return false;
    }
    err = nvs_commit(my_handle);
    if (ESP_OK != err)
    {
        nvs_close(my_handle);
        return false;
    }
    nvs_close(my_handle);
    return true;
}

bool nvs_shan_chu_key(jsonJP jsonP)
{
    nvs_handle my_handle;
    esp_err_t err;
    // 打开NVS分区
    err = nvs_open(jsonP->ips, NVS_READWRITE, &my_handle);
    if (err != ESP_OK)
    {
        nvs_close(my_handle);
        return false;
    }
    err = nvs_erase_key(my_handle, jsonP->vvs);
    if (ESP_OK != err)
    {
        nvs_close(my_handle);
        return false;
    }
    err = nvs_commit(my_handle);
    if (ESP_OK != err)
    {
        nvs_close(my_handle);
        return false;
    }
    nvs_close(my_handle);
    return true;
}

bool zhong_duan_sheng_xiao_shi_jian()
{
    esp_err_t err;
    err = nvs_get_u16(ZIDINGYI_NVS_KONG_JIAN, "kaiShiShi", &kaiShiShi);
    if (err != ESP_OK)
    {
        return false;
    }
    err = nvs_get_u16(ZIDINGYI_NVS_KONG_JIAN, "jieShuShi", &jieShuShi);
    if (err != ESP_OK)
    {
        return false;
    }
    err = nvs_get_u16(ZIDINGYI_NVS_KONG_JIAN, "kaiShiFen", &kaiShiFen);
    if (err != ESP_OK)
    {
        return false;
    }
    err = nvs_get_u16(ZIDINGYI_NVS_KONG_JIAN, "jieShuFen", &jieShuFen);
    if (err != ESP_OK)
    {
        return false;
    }
    return true;
}

int16_t shi_jian_dui_bi_shi(uint16_t kaiShi, uint16_t jieShu, uint16_t kaiShiFen, uint16_t jieShuFen)
{
    // 定义一个名为now的变量，类型为time_t，用于存储时间戳
    time_t now;
    // 定义一个字符数组strftime_buf，用于存储格式化后的日期和时间字符串
    char strftime_buf[64];
    // 定义一个名为timeinfo的结构体，用于存储日期和时间信息
    struct tm timeinfo;
    // 调用time函数获取当前时间戳并存储在now变量中
    time(&now);
    // 设置环境变量'TZ'的值，将时区设置为中国标准时间（CST-8）
    // 这将影响后续的日期和时间转换
    setenv("TZ", "CST-8", 1);
    // 调用tzset函数根据环境变量'TZ'的值设置本地时区信息
    tzset();
    // 调用localtime_r函数将当前时间戳转换（本地化）为本地时间，并将结果存储在timeinfo结构体中
    localtime_r(&now, &timeinfo);
#if TIAO_SHI == 1
    ESP_LOGI(TAG, "dangqian时间戳 = %lld,  #  kaishi:%d   #  jieShu:%d\n", now, kaiShi, jieShu);
    // 调用strftime函数根据指定的格式将本地时间转换为字符串，并存储在strftime_buf中
    // strftime函数的第一个参数是输出字符串的缓冲区，第二个参数是缓冲区的大小，第三个参数是格式化字符串'%c'，表示格式化为本地日期和时间字符串
    strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
    // 使用ESP_LOGI函数打印出当前在中国标准时间下的日期和时间
    ESP_LOGI(TAG, "现在是北京时间: %s\r\n", strftime_buf);
    // ESP_LOGI(TAG, "今年是: %d\r\n", timeinfo.tm_year);
#endif
    if (timeinfo.tm_year < 123) // 是否到了2023年
    {
        ESP_LOGI(TAG, "cuo wu 1\n");
        return 1; // 时间未同步
    }
    if (kaiShi < jieShu) // 处理跨午夜的时间段
    {
        if ((uint16_t)timeinfo.tm_hour < kaiShi || (uint16_t)timeinfo.tm_hour >= jieShu) // 当前时间(小时)是否在设定时间内;13-17
        {
            return -1; // 不在范围内12
        }
    }
    else
    {
        if ((uint16_t)timeinfo.tm_hour < kaiShi && (uint16_t)timeinfo.tm_hour >= jieShu) // 17-6
        {
            return -1; // 16
        }
    }
    if ((uint16_t)timeinfo.tm_hour == kaiShi)
    {
        if ((int16_t)timeinfo.tm_min < kaiShiFen) // 当前时间(分)是否在设定时间内
        {
            return -1; //
        }
    }
    if ((uint16_t)timeinfo.tm_hour == (jieShu - 1))
    {                                             // 50>30;51-29
        if ((int16_t)timeinfo.tm_min > jieShuFen) // 当前时间(分)是否在设定时间内
        {
            return -1; //
        }
    }

    return 0; // 成功
}

bool json_chu_li(const char *data)
{
    ESP_LOGI(TAG, "json = %s\n", data);
    cJSON *root = cJSON_Parse(data); // 解析 JSON 字符串
    if (root != NULL)
    {
        cJSON *_lx = cJSON_GetObjectItemCaseSensitive(root, "lx");
        if (_lx == NULL)
        {
            cJSON_Delete(root);
            return false;
        }
        uint16_t lx = (uint16_t)(_lx->valueint);

        if (lx == 1)
        {
            if (xQueueSend(ledPwmLD, &lx, portMAX_DELAY) != pdPASS)
            {
                cJSON_Delete(root);
                return false;
            }
            cJSON_Delete(root);
            return true;
        }

        jsonJ sj;
        sj.jieShu = 0;
        sj.kaiShi = 0;
        sj.lx = lx;
        if (sj.lx > 10 && sj.lx <= 20)
        {
            // ESP_LOGI(TAG, "lx = %d\n", sj.lx);
            if (xQueueSend(kongZhiLD, (void *)&sj, portMAX_DELAY) != pdPASS)
            {
                cJSON_Delete(root);
                return false;
            }
            cJSON_Delete(root);
            return true;
        }

        cJSON *_id = cJSON_GetObjectItemCaseSensitive(root, "id");
        if (_id == NULL)
        {
            cJSON_Delete(root);
            return false;
        }
        char *id = _id->valuestring;
        uint16_t len = data_len(id);
        for (uint16_t i = 0; i < len; i++)
        {
            sj.id[i] = id[i];
        }
        sj.id[len] = '\0';
        if (strcmp(id, sbm) != 0)
        {
            cJSON_Delete(root);
            return false;
        }
        if (sj.lx <= 10)
        {
            if (xQueueSend(ledPwmLD, &lx, portMAX_DELAY) != pdPASS)
            {
                cJSON_Delete(root);
                return false;
            }
            cJSON_Delete(root);
            return true;
        }
        if (sj.lx > 20 && sj.lx <= 30)
        {
            cJSON *_ips = cJSON_GetObjectItemCaseSensitive(root, "ips");
            if (_ips != NULL)
            {
                char *ips = _ips->valuestring;
                len = data_len(ips);
                for (uint16_t i = 0; i < len; i++)
                {
                    sj.ips[i] = ips[0];
                }
                sj.ips[len] = '\0';
            }
            cJSON *_vvs = cJSON_GetObjectItemCaseSensitive(root, "vvs");
            if (_vvs != NULL)
            {
                char *vvs = _vvs->valuestring;
                len = data_len(vvs);
                for (uint16_t i = 0; i < len; i++)
                {
                    sj.vvs[i] = vvs[0];
                }
                sj.vvs[len] = '\0';
            }
        }
        if (sj.lx > 30)
        {
            cJSON *_ksi = cJSON_GetObjectItemCaseSensitive(root, "ksi");
            if (_ksi != NULL)
            {
                sj.kaiShi = (uint16_t)(_ksi->valueint);
            }
            cJSON *_jsi = cJSON_GetObjectItemCaseSensitive(root, "jsi");
            if (_jsi != NULL)
            {
                sj.jieShu = (uint16_t)(_jsi->valueint);
            }
        }
        if (xQueueSend(kongZhiLD, (void *)&sj, portTICK_PERIOD_MS) != pdPASS)
        {
            cJSON_Delete(root);
            return false;
        }
        cJSON_Delete(root);
        return true;
    }
    cJSON_Delete(root);
    return false;
}

uint16_t data_len(const char *data)
{
    uint16_t i;
    for (i = 0; data[i]; i++)
    {
    }
    return i + 1;
}

bool nvs_bao_cun_shi_jian(jsonJP jsP)
{
    nvs_handle_t my_handle;
    esp_err_t err;

    // Open
    err = nvs_open(ZIDINGYI_NVS_KONG_JIAN, // 命名空间名称
                   NVS_READWRITE,          // NVS_READWRITE 或 NVS_READONLY。如果 NVS_READONLY，将打开一个只读句柄。
                   &my_handle);            // 如果成功（返回代码为零），句柄将在此参数中返回。
    if (err != ESP_OK)
    {
        return false;
    }
    if (jsP->lx == 31)
    {
        err = nvs_set_u16(my_handle, "kaiShiShi", jsP->kaiShi);
        if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND)
        {
            // ESP_LOGI(TAG, "kaiShiShi\n");
            nvs_close(my_handle);
            return false;
        }
        err = nvs_set_u16(my_handle, "jieShuShi", jsP->jieShu);
        if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND)
        {
            // ESP_LOGI(TAG, "jieShuShi\n");
            nvs_close(my_handle);
            return false;
        }
    }
    if (jsP->lx == 32)
    {
        err = nvs_set_u16(my_handle, "kaiShiFen", jsP->kaiShi);
        if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND)
        {
            nvs_close(my_handle);
            return false;
        }
        err = nvs_set_u16(my_handle, "jieShuFen", jsP->jieShu);
        if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND)
        {
            nvs_close(my_handle);
            return false;
        }
    }
    //  必须调用 nvs_commit() 以确保更改写入闪存。
    err = nvs_commit(my_handle);
    if (err != ESP_OK)
    {
        return false;
    }

    // 关闭存储句柄并释放所有分配的资源
    nvs_close(my_handle);
    return true;
}
#if 0
void ping_task(void *pvParameter)  
{  uint16_t jiShi =0;
    esp_ping_config_t ping_config = {  
        .count = 4, // 发送的ping请求数量  
        .timeout_ms = PING_TIMEOUT, // 超时时间  
        .target_addr = ROUTER_IP, // 目标IP地址  
    };  
    esp_ping_handle_t ping_handle = esp_ping_new_session(&ping_config);  
    if (ping_handle == NULL) {  
        printf("无法创建 ping 会话\n");  
        return;  
    }  
  
    esp_err_t err = esp_ping_start(ping_handle);  
    if (err != ESP_OK) {  
        printf("无法启动 ping: %s\n", esp_err_to_name(err));  
        esp_ping_delete_session(ping_handle);  
        return;  
    }  
  
    // 等待ping操作完成或超时  
    int status = -1;  
    while (status == -1) {  
        err = esp_ping_start(ping_handle);  
        if (err != ESP_OK) {  
            printf("无法获取 ping 状态: %s\n", esp_err_to_name(err));  
            break;  
        }  
        vTaskDelay(pdMS_TO_TICKS(1000)); // 等待一段时间再次检查状态  
    }  
  
    // 处理ping结果  
    if (status == 0) {  
        printf("Ping successful\n");  
    } else {  
        printf("Ping failed\n");  
    }  
  
    // 清理ping会话  
    esp_ping_delete_session(ping_handle);  
    vTaskDelete(NULL); // 删除任务句柄，结束任务  
}
#endif

#if SHIJIAN == 1
void shi_jian_jiao_jun(const char *data)
{
    int64_t shiJianJ = shi_jian_xiao_zhun(data);
    struct timeval tv;
    tv.tv_sec = shi_jian_xiao_zhun(data);
    tv.tv_usec = 0;          // 微秒数
    settimeofday(&tv, NULL); // 校准时间
}

void shi_jian_xiang(const char *data)
{

    // 定义一个名为now的变量，类型为time_t，用于存储时间戳
    time_t now;

    // 定义一个字符数组strftime_buf，用于存储格式化后的日期和时间字符串
    char strftime_buf[64];

    // 定义一个名为timeinfo的结构体，用于存储日期和时间信息
    struct tm timeinfo;

    // 调用time函数获取当前时间戳并存储在now变量中
    time(&now);
    printf("000006d = %lld\n", now);

    // 设置环境变量'TZ'的值，将时区设置为中国标准时间（CST-8）
    // 这将影响后续的日期和时间转换
    setenv("TZ", "CST-8", 1);

    // 调用tzset函数根据环境变量'TZ'的值设置本地时区信息
    tzset();

    // 调用localtime_r函数将当前时间戳转换（本地化）为本地时间，并将结果存储在timeinfo结构体中
    localtime_r(&now, &timeinfo);

    // 调用strftime函数根据指定的格式将本地时间转换为字符串，并存储在strftime_buf中
    // strftime函数的第一个参数是输出字符串的缓冲区，第二个参数是缓冲区的大小，第三个参数是格式化字符串'%c'，表示格式化为本地日期和时间字符串
    strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);

    // 使用ESP_LOGI函数打印出当前在中国标准时间下的日期和时间
    ESP_LOGI(TAG, "The current date/time in Shanghai is: %s", strftime_buf);

    int64_t shiJianJ = shi_jian_xiao_zhun(data);
    printf("0000ddd = %lld\n", shiJianJ);
    struct timeval tv;
    ESP_LOGI(TAG, "000001\n");
    tv.tv_sec = shi_jian_xiao_zhun(data);
    tv.tv_usec = 0; // 微秒数
    ESP_LOGI(TAG, "000002\n");
    settimeofday(&tv, NULL);
    ESP_LOGI(TAG, "000003\n");
    time(&now);
    printf("000004d = %lld\n", now);
    // gettimeofday(tv.tv_sec, NULL);
    printf("Current time: %lld.%06ld seconds\n", tv.tv_sec, tv.tv_usec);
}

int64_t shi_jian_xiao_zhun(const char *data)
{                              // wwlo\1702120954
    size_t len = strlen(data); // 计算字符串长度,不含结尾的'\0'
    char ls[16] = {0};
    uint16_t i = 0;
    uint16_t ii = 0;
    for (; ii < len; ii++)
    {
        // ls[i] = data[ii];
        if (data[ii] == '\\')
        {
            break;
        }
    }
    ii++;
    for (; ii < len; ii++)
    {
        ls[i] = data[ii];
        i++;
    }
    int64_t dataU64 = atoi(ls);
    return dataU64;
}

#endif